package com.app.net;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.app.util.Utils_Log;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;




/**
 * @author sinawear 540126629@qq.com
 */
public abstract class NetHelper2 {

	public static final String TAG_URL = "remark url for cancel.";
	public static final String TAG = "NetHelper2";


	private static boolean DEBUG = true;
	private final int SOCKET_TIMEOUT = 10 * 100; // volley 默认2.5s

	private com.android.volley.RequestQueue requestQueue;
	private Context context;

	// 需要的两个参数
	private String url = "";
	private Map<String, Object> map = new HashMap<String, Object>();



	public NetHelper2(com.android.volley.RequestQueue requestQueue) { //
		// TODO Auto-generated constructor stub
		this.requestQueue = requestQueue;

	}

	public NetHelper2(Context context) { //
		this.context = context;

	}


	// 错误处理
	// http://www.airuanw.com/article/ar3531.html

	// 请求取消参考
	// https://github.com/BoyanAtMentormate/VolleySample/blob/master/VolleySimpleSample/src/main/java/com/example/volleysimplesample/VolleyActivity.java

	Handler handler = new Handler() {

		public void handleMessage(Message msg) {

			if (msg.what == -1) {
				// Utils1.showToastShort(AppUtils.context_app, "网络连接异常!");
				Utils_Log.e(TAG, "sorry,Error: "+" >>>> "+url);
				String StatusCode = (String) msg.obj;
				OnError(StatusCode);
				OnFinal();
				return;
			}

			String str = (String) msg.obj;
//			if (DEBUG)
//				System.out.println(str);

			String result = str;
			try {

				JSONObject json_obj = new JSONObject(str);
				result = json_obj.toString();
				OnComplete(str);

			} catch (JSONException e) {
				e.printStackTrace();
				System.out.println("JSONException: " + e.getMessage());
			}
			finally{
				Utils_Log.e(TAG, url+" >>>> "+result);
				OnCompleteRaw(result);
				OnFinal();
			}

		};
	};



	//---
	public abstract String thread_init(Map<String, Object> map);
	public abstract void OnComplete(String message) throws JSONException; // 并不会强制要函数体内,必须会有json异常跑出呢..

	public void init() {}
	public void thread_OnComplete(String message) throws JSONException {}
	public void OnCompleteRaw(String message){}
	public void OnFinal(){}


	/**
	 * 因为OnError要依赖handler，在AppException中就不能正常了
	 *
	 * @param StatusCode
	 */
	public void thread_OnError(String StatusCode) {

	}

	/**
	 * 返回值两种情况; 1)空字符串，网络完全不通； 2）服务器返回的code;
	 *
	 * @param StatusCode
	 */
	public void OnError(String StatusCode) {

	}
	//---


	private void volley_post() {

		StringRequest StringRequest = new StringRequest(Request.Method.POST,
				url, new Response.Listener<String>() {
					@Override
					public void onResponse(String strNetRespone) {

						try {
							thread_OnComplete(strNetRespone);

							Message msg = new Message();
							msg.obj = strNetRespone;
							msg.what = 0;
							handler.sendMessage(msg);
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
				}, new Response.ErrorListener() {
					@Override
					public void onErrorResponse(VolleyError arg0) {

						String StatusCode = "";

						if (arg0 != null) {
							String message = arg0.getMessage();
							if (message != null)
								System.out.println(message);

							NetworkResponse response = arg0.networkResponse;
							if (response != null)
								StatusCode = "" + response.statusCode;
						}

						thread_OnError(StatusCode);

						Message msg = new Message();
						msg.obj = StatusCode;
						msg.what = -1;
						handler.sendMessage(msg);

					}

				}) {



			  // 发送请求
			  @Override
				public Map<String, String> getHeaders()
						throws AuthFailureError {

					Map<String, String> headers = new HashMap<String, String>();

					// 发送请求
					//  headers.put("Charset", "UTF-8");
					//  headers.put("Content-Type","application/json");

					return headers;

				};

			@Override
			public RetryPolicy getRetryPolicy() {
				// TODO Auto-generated method stub
				return super.getRetryPolicy();
			}

			@Override
			protected Map<String, String> getParams() throws AuthFailureError {
				// TODO Auto-generated method stub

				Map<String, String> temp_map = new HashMap<String, String>();

				// 添加body
				for(Map.Entry<String, Object> item : map.entrySet()){
					if(item.getValue() instanceof String)
						temp_map.put(item.getKey(), (String)item.getValue());

				}

				return temp_map;

			}

		};

		try {

			String Headers = StringRequest.getHeaders().toString();
			String body_content_type = StringRequest.getBodyContentType();
			Utils_Log.d(TAG, "headers: " + Headers);
			Utils_Log.d(TAG, "body content type: " + body_content_type);

		} catch (AuthFailureError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

		StringRequest.setTag(TAG_URL);
		requestQueue.add(StringRequest);

	}

	private void volley_get() {

		StringRequest StringRequest = new StringRequest(Request.Method.GET,
				url, new Response.Listener<String>() {

					@Override
					public void onResponse(String strNetRespone) {
						//System.out.println("strNetRespone=" + strNetRespone);

						try {
							thread_OnComplete(strNetRespone);

							Message msg = new Message();
							msg.obj = strNetRespone;
							msg.what = 0;
							handler.sendMessage(msg);
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
				}, new Response.ErrorListener() {
					@Override
					public void onErrorResponse(VolleyError error) {
						//System.out.println("sorry,Error: " + url);

						if (error instanceof NetworkError) {
							// } else if( error instanceof ClientError) {
						} else if (error instanceof ServerError) {
						} else if (error instanceof AuthFailureError) {
						} else if (error instanceof ParseError) {
						} else if (error instanceof NoConnectionError) {
							System.out.println("NoConnectionError");
						} else if (error instanceof TimeoutError) {
							System.out.println("TimeoutError");
						}

						String StatusCode = "";

						if (error != null) {
							String message = error.getMessage();
							if (message != null)
								System.out.println(message); // 也可以""+null;
							// 得到返回code 如果是断网状态response返回为null
							NetworkResponse response = error.networkResponse;
							if (response != null)
								StatusCode = "" + response.statusCode;
						}

						Message msg = new Message();
						msg.obj = StatusCode;
						msg.what = -1;
						handler.sendMessage(msg);

					}

				}) {

			// http://bUtils_Log.csdn.net/hpb21/article/details/12163371
			@Override
			public RetryPolicy getRetryPolicy() {
				RetryPolicy retryPolicy = new DefaultRetryPolicy(
						SOCKET_TIMEOUT, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
						DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

				return retryPolicy;
			}

		};

		try {
			String Headers = StringRequest.getHeaders().toString();
			String body_content_type = StringRequest.getBodyContentType();
		//	int TimeoutMs = StringRequest.getTimeoutMs();
			Utils_Log.d(TAG, "headers: " + Headers);
			Utils_Log.d(TAG, "body content type: " + body_content_type);
	//		System.out.println("TimeoutMs: " + TimeoutMs);

		} catch (AuthFailureError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

		StringRequest.setTag( TAG_URL );
		requestQueue.add(StringRequest);

	}


	private String httpGetHelper() {


		String jsonString = "";
		InputStream inputStream = null;
		try {
			BasicHttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams, 20000);
			HttpConnectionParams.setSoTimeout(httpParams, 20000); //
			HttpClient client = new DefaultHttpClient(httpParams);

			HttpGet request = new HttpGet(url );
			Utils_Log.e(TAG, "------------------------------------------------");
			Utils_Log.e(TAG, "URL=" + url);
			HttpResponse response = client.execute(request);

			HttpEntity httpEntity = response.getEntity();
			int StatusCode = response.getStatusLine().getStatusCode();
			if (DEBUG)
				Utils_Log.e(TAG, "StatusCode=" + StatusCode);

			if (StatusCode == 200) {
				inputStream = httpEntity.getContent();
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(inputStream));
				String result = "";
				String line = "";
				while ((line = reader.readLine()) != null) {
					result = result + line;
				}
				inputStream.close();
				jsonString = result;
			}

			return jsonString;

		} catch (Exception e) {
			e.printStackTrace();
			Utils_Log.e(TAG, e.toString());

			return "";
		}

	}

	private String httpPostHelper() {

		// 转换数据结构
		ArrayList<BasicNameValuePair> parameters = new ArrayList<>();
		for(Map.Entry<String, Object> item : map.entrySet()){
			if(item.getValue() instanceof String)
				parameters.add(new BasicNameValuePair(item.getKey(), (String)item.getValue()));
		}


		String jsonString = "";
		try {

			HttpPost post = new HttpPost(url);
			Utils_Log.e(TAG, "------------------------------------------------");
			Utils_Log.e(TAG, "url=" + url);
			Utils_Log.e(TAG, "parameters=" + parameters.toString());
			BasicHttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams, 20000);
			HttpConnectionParams.setSoTimeout(httpParams, 1 * 60 * 1000);
			post.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));
			HttpResponse response = new DefaultHttpClient(httpParams)
					.execute(post);

			int StatusCode = response.getStatusLine().getStatusCode();
			if (DEBUG)
				Utils_Log.e(TAG, "StatusCode=" + StatusCode);

			if (StatusCode == 200)
				jsonString = EntityUtils
						.toString(response.getEntity(), "UTF-8");
			else {
				thread_OnError("" + StatusCode);
			}

			return jsonString;

		} catch (Exception e) {
			e.printStackTrace();
			Utils_Log.e(TAG, e.toString());
			return jsonString;
		}

	}





	public void start_POST(){

		init();

		new Thread() {

			public void run() {

				map.clear();
				url = thread_init(map);
				if (url.length() == 0)
					return;

				Utils_Log.e(TAG, "------------------------------------------------");
				Utils_Log.e(TAG, "url=" + url);
				Utils_Log.e(TAG, "parameters=" + map.toString());


				if (context == null)
					volley_post();
				else {
					httpPostHelper();
				}

			};
		}.start();


	}


	// http://www.cnblogs.com/devinzhang/archive/2012/01/08/2316453.html
	public void start_GET() {

		init();

		new Thread() {

			public void run() {

				map.clear();
				url = thread_init(map);
				if (url.length() == 0)
					return;



				StringBuilder params = new StringBuilder("");
				try{
					if (map != null) {
						params.append("?");

						for (Map.Entry<String, Object> entry : map.entrySet()) {

							params.append(entry.getKey());
							params.append("=");
							params.append(URLEncoder.encode((String)entry.getValue(), "UTF-8"));
							params.append("&");
						}
					}
				}
				catch (Exception e){
					e.printStackTrace();
				}



				Utils_Log.e(TAG, "------------------------------------------------");
				Utils_Log.e(TAG, "url=" + url);
				Utils_Log.e(TAG, "params=" + params);

				url = url + params;
				Utils_Log.e(TAG, "result url=" + url);

				if (context == null) {
					volley_get();
				} else {
					httpGetHelper();
				}

			};
		}.start();

	}



}
